package com.zone.binding;

import cn.hutool.core.lang.ClassScanner;
import com.zone.session.SqlSession;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author: zongzi
 * @description: TODO
 * @date: 2023/11/29
 */
public class MapperRegistry {

    private final Map<Class<?>, MapperProxyFactory<?>> map = new HashMap<>();

    /**
     * 获取映射器代理对象
     *
     * @param clazz
     * @param sqlSession
     * @param <T>
     * @return
     */
    public <T> T getMapper(Class<T> clazz, SqlSession sqlSession) {
        final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) map.get(clazz);
        if (mapperProxyFactory == null) {
            throw new RuntimeException("get mapper fail not know clazz = " + clazz.getName());
        }
        return mapperProxyFactory.newProxy(sqlSession);
    }

    /**
     * 判断内部map是否已经添加过映射器
     *
     * @param type
     * @param <T>
     * @return
     */
    public <T> boolean hasMapper(Class<T> type) {
        return map.containsKey(type);
    }

    /**
     * 注册指定的mapper
     *
     * @param clazz
     * @param <T>
     */
    public <T> void addMapper(Class<T> clazz) {
        // 如果时接口才进行注册
        if (clazz.isInterface()) {
            if (this.hasMapper(clazz)) {
                throw new RuntimeException("clazz = " + clazz.getName() + "mapper already regis");
            }
            MapperProxyFactory<T> mapperProxyFactory = new MapperProxyFactory<>(clazz);
            map.put(clazz, mapperProxyFactory);
        }
    }

    /**
     * 注册指定包名下所有的mapper
     *
     * @param packageName
     */
    public void addMappers(String packageName) {
        assert packageName != null;
        assert !packageName.equals("");
        Set<Class<?>> classes = ClassScanner.scanPackage(packageName);
        for (Class<?> clazz : classes) {
            this.addMapper(clazz);
        }
    }


}
